package com.wstuo.common.rules.parser;

import com.wstuo.common.config.dictionary.dao.IDataDictionaryItemsDAO;
import com.wstuo.common.rules.entity.Rule;
import com.wstuo.common.rules.entity.RuleAction;
import com.wstuo.common.rules.entity.RuleConstraint;
import com.wstuo.common.rules.entity.RulePackage;
import com.wstuo.common.rules.entity.RulePattern;
import com.wstuo.common.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

/**
 * RuleParser
 * @author QXY
 * @version 0.1 2010.9.17
 */
public class RuleParser{
	

	@Autowired
	private IDataDictionaryItemsDAO dataDictionaryItemsDAO;
	
    private String andOr="or";
    
    public String getAndOr() {
		return andOr;
	}

	public void setAndOr(String andOr) {
		this.andOr = andOr;
	}


	/**
     * 根据规则文本，获取RulePackage
     * @param text
     * @return RulePackage
     * @exception IOException
     */
    public RulePackage parser(String text) throws IOException{
    
    	 BufferedReader br = new BufferedReader(new StringReader(text));
         String line = null;
         RulePackage rulePackage = new RulePackage();
         rulePackage.setLocation(new Date().getTime()+".drl");//默认地址
         
         List<Rule> rules=new ArrayList<Rule>();
         Rule rule=null;

         while ((line = br.readLine()) != null){

        	 if (line.contains("package")){
        		 rulePackage.setPackageName(line.substring(7).trim());
             }

             if (line.contains("import")){
            	 
            	 String imports=line;
            	 imports=imports.replace("import", "").trim();
            	 rulePackage.setImports(imports);
             }

             if (line.contains("rule")){
            	 rule=new Rule();
            	 rule.setRuleName(((line.trim().split("\\ "))[1]).replace("\"",""));//取得规则名称
             }

             if (line.contains("dialect")){
                 String dialect = line.substring(11).trim();
                 dialect = dialect.replace("\"", "");
                 rule.setDialect(dialect);
             }
             if (line.contains(":")){
            	 setRuleConstraint(rule,line);//设置Constraint
             }
             if (line.contains("modify")){
            	 setRuleAction(rule,line);
             }
             if (line.contains("end")){
            	 rules.add(rule);
             }
         }

        rulePackage.setRules(rules);

    	return rulePackage;
    }

    /**
     * 取得规则集.
     * @param rule
     * @param str
     */
    public void setRuleConstraint(Rule rule,String str){
    	
    	String [] arr1=str.trim().split(":");//dto:RequestDTO(etitle matches ".*Van.*")
    	String [] arr2=arr1[1].split("\\(");//RequestDTO,etitle matches ".*Van.*")
    	
    	RulePattern patten=new RulePattern();
    	patten.setPatternBinding(arr1[0]);//dto
    	patten.setPatternType(arr2[0]);//RequestDTO
    	
    	String constraintsStr=arr2[1].replace(")", "");
    	String [] arr3=constraintsStr.split(",");//尝试使用and
    	if(arr3.length<=1){//当使用“,”截取不到，再尝试使用“||”
    		arr3=constraintsStr.split("\\|\\|");//注意转意写法
    		andOr="or";
    	}
    	if(arr3.length>0){//存在规则集
    		
    		List<RuleConstraint> rcs=new ArrayList<RuleConstraint>();
        	for(String s:arr3){
        		if(StringUtils.hasText(s)){
        			rcs.add(getConstraint(s));//调用方法，取得规则详情
        		}
        	}
        	patten.setConstraints(rcs);
    	}
    	
    	rule.setCondition(patten);
    }

    /**
     * 根据相关字符串，取得Constraint详情.
     * @param str
     * @return RuleConstraint
     */
    public RuleConstraint getConstraint(String str){
   
    	RuleConstraint ruleConstraint=new RuleConstraint();
    	
    	String [] cons;
    	String PropertyName="";
    	String propertyValue="";
    	String propertyValueName="";
    	
    	if(str.indexOf("=")!=-1){
    		cons=str.trim().replace("  ", " ").split("=");
    		PropertyName=cons[0];
    		propertyValue=cons[1];
    		
    	}else{
    		cons=str.trim().replace("  ", " ").split(" ");//去除左右空格，将多个空格的替换为一个空格
    		PropertyName=cons[0]+" "+cons[1];
    		propertyValue=cons[2];
    	}
    	

    	if (propertyValue.contains("\"")){
         	propertyValue = propertyValue.replace("\"", "");
         	ruleConstraint.setPropertyType(true);
        }else{
        	ruleConstraint.setPropertyType(false);
        }
    	
    	if(cons[0].equals("etitle")||cons[0].equals("edesc")){
    		propertyValueName=propertyValue.replace(".*", "");
    	}
    	
    	else if(cons[0].equals("priorityNo")||cons[0].equals("seriousnessNo")||cons[0].equals("effectRangeNo")||cons[0].equals("levelNo")||cons[0].equals("imodeNo")){
    		
    		propertyValue=propertyValue.trim().replace("L", "");
    		propertyValueName=dataDictionaryItemsDAO.findById(Long.parseLong(propertyValue)).getDname();
    	}
    	
    	ruleConstraint.setPropertyName(PropertyName);
    	ruleConstraint.setPropertyValue(propertyValue);
    	ruleConstraint.setPropertyValueName(propertyValueName);
    	
    	
    	return ruleConstraint;
    }
    
    
    /**
     * 设置动作集。
     * @param rule
     * @param str
     */
    public void setRuleAction(Rule rule,String str){
    	
    	String [] arr=str.split("\\{");
    	String arrs=arr[1].replace("}", "").trim();
    	String [] arrAction=arrs.split(",");
    	
    	
    	List<RuleAction> actions=new ArrayList<RuleAction>();
    	
    	for(String action:arrAction){
    		
    		RuleAction ruleAction=new RuleAction();
    		
    		String [] dt = action.split("=");
    		
    		ruleAction.setAndOr(andOr);
    		ruleAction.setPropertyName(dt[0]);
    		String givenValue=dt[1].replace("\"", "");
    		
    		if(dt[1].indexOf("\"")==-1){
    			givenValue=givenValue.replace("L", "");
    			ruleAction.setDataFlag(((Number)1).byteValue());
    			ruleAction.setDataType("Long");
    		}else{
    			ruleAction.setDataFlag(((Number)0).byteValue());
    			ruleAction.setDataType("String");
    		}
    		ruleAction.setGivenValue(givenValue);
    		ruleAction.setRule(rule);
    		actions.add(ruleAction);
    	}
    	rule.setActions(actions);
    }
}
